import os
from typing import List
from dataclasses import dataclass
import requests
import uuid
from Enum import FileModelEnum
from TrainModel.KNNClassifier import KNNClassifier
from TrainModel.KELMClassifier import KELMClassifier

@dataclass
class RemoteFileTrainAddRequest:
    """
    远程文件添加请求类
    """
    id: int  # 训练编号
    url: str  # 文件存储 url，用于下载对应文件
    model: str  # 训练模型
    trainRate: int  # 训练占比（单位百分比）
    isRefresh: int  # 是否数据洗牌
    selectFeatures: List[int]  # 筛选特征，列号JSON数组
    selectTargets: List[int]  # 筛选目标，列号JSON数组
    fileId: int  # 文件Id
    userId: int  # 创建用户 id，用于校验


class doFileTrainExecute:

    def createPath(self, prefix: str, userId: str, fileId: str, model: str, trainId: str):
        path = prefix
        # 用户路径
        path = os.path.join(path, "user-" + userId)
        if not os.path.exists(path):
            os.makedirs(path)

        # 文件路径
        path = os.path.join(path, "file-" + fileId)
        if not os.path.exists(path):
            os.makedirs(path)

        # 模型以及训练路径
        path = os.path.join(path, f"{str(model)}-{trainId}")
        if not os.path.exists(path):
            os.makedirs(path)

        return path

    def doFileTrain(self, remoteFileTrainAddRequest: RemoteFileTrainAddRequest):
        # 根据url下载数据
        url = remoteFileTrainAddRequest.url
        userId = remoteFileTrainAddRequest.userId
        fileId = remoteFileTrainAddRequest.fileId
        trainId = remoteFileTrainAddRequest.id
        selectFeatures = remoteFileTrainAddRequest.selectFeatures
        selectTargets = remoteFileTrainAddRequest.selectTargets
        isRefresh = remoteFileTrainAddRequest.isRefresh
        trainRate = remoteFileTrainAddRequest.trainRate / 100

        ## 1.构建存储路径
        # 获取当前工作目录
        user_dir = os.getcwd()

        # 兼容不同系统的路径分隔符
        global_file_dir_name = 'TEMP_FILE_TRAIN'  # 你可以根据需要设置这个值
        global_file_path_name = os.path.join(user_dir, global_file_dir_name)

        # 判断全局目录是否存在，没有则新建
        if not os.path.exists(global_file_path_name):
            os.makedirs(global_file_path_name)

        save_path = ""

        ## 2.下载文件
        try:
            # 发送GET请求下载文件
            response = requests.get(url)
            response.raise_for_status()  # 检查请求是否成功

            # 获取文件名和后缀
            file_name, file_extension = os.path.splitext(os.path.basename(url))

            save_path = os.path.join(global_file_path_name, f"{str(uuid.uuid4())}{file_extension}")

            # 将文件内容写入到指定路径
            with open(save_path, 'wb') as file:
                file.write(response.content)
            print(f"文件已成功下载并保存到: {save_path}")

        except requests.exceptions.RequestException as e:
            print(f"下载文件时发生错误: {e}")

        ## 3.构造存储路径
        ## /train/{userId}/{fileId}/{model}{tainId}/
        ## 训练目录
        fileTrainResultPrefix = os.path.join(user_dir, "train")
        # 判断目录是否存在，没有则新建
        if not os.path.exists(fileTrainResultPrefix):
            os.makedirs(fileTrainResultPrefix)

        ## 4.选择模型
        model = remoteFileTrainAddRequest.model
        resultPath = ""
        result = {}
        if FileModelEnum.KNN.value == model:
            resultPath = self.createPath(fileTrainResultPrefix, str(userId), str(fileId), model, str(trainId))
            knn_classifier = KNNClassifier(save_path, selectFeatures, selectTargets, resultPath, isRefresh, trainRate)
            result = knn_classifier.run()

        elif FileModelEnum.SVM.value == model:
            resultPath = self.createPath(fileTrainResultPrefix, str(userId), str(fileId), model, str(trainId))


        elif FileModelEnum.FKNN.value == model:
            resultPath = self.createPath(fileTrainResultPrefix, str(userId), str(fileId), model, str(trainId))


        elif FileModelEnum.KELM.value == model:
            resultPath = self.createPath(fileTrainResultPrefix, str(userId), str(fileId), model, str(trainId))
            kelm_classifier = KELMClassifier(save_path, selectFeatures, selectTargets, resultPath, isRefresh, trainRate)
            result = kelm_classifier.run()

        ## 4. 删除临时文件
        if os.path.exists(save_path):
            os.remove(save_path)  # 删除文件
            print(f"{save_path} 被成功删除")
        else:
            print(f"文件 {save_path} 不存在")


        return result
